package com.qkl.xiatang.app.service.impl;

import com.qkl.xiatang.app.cache.LocalCacheBuilder;
import com.qkl.xiatang.app.cache.LocalSimpleCache;
import com.qkl.xiatang.app.dto.mqtt.DeviceData;
import com.qkl.xiatang.app.dto.mqtt.MqttReceiveDTO;
import com.qkl.xiatang.app.entity.device.DeviceInfo;
import com.qkl.xiatang.app.mapper.DeviceDataMapper;
import com.qkl.xiatang.app.mapper.DeviceInfoMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Service
@Slf4j
public class MqttDeviceService {

    @Autowired
    private DeviceDataMapper deviceDataMapper;

    @Autowired
    private DeviceInfoMapper deviceInfoMapper;

    private LocalSimpleCache<Map<String,DeviceInfo>> deviceInfoCache;

    public void addMqttReceiveData(MqttReceiveDTO receiveData){
        try {
            this.addDeviceInfo(receiveData.getSn());

            DeviceData deviceData = receiveData.getData();
            deviceData.setSn(receiveData.getSn());
            deviceData.setTs(receiveData.getTs());
            this.addDeviceData(deviceData);
            deviceDataMapper.addDeviceDataPond(deviceData);
        }catch (Exception e){
            log.error("addMqttReceiveData exception.error message:{}",e);
        }
    }

    public void addDeviceInfo(DeviceInfo deviceInfo){
        deviceInfoMapper.insert(deviceInfo);
    }

    public void addDeviceInfo(String sn){
        if(!deviceInfoCache.getCache().containsKey(sn)){
            synchronized (deviceInfoCache) {
                if(!deviceInfoCache.refreshCache().containsKey(sn)) {
                    Date date = new Date();
                    DeviceInfo deviceInfo = new DeviceInfo();
                    deviceInfo.setCreateBy("mqtt");
                    deviceInfo.setUpdateBy("mqtt");
                    deviceInfo.setCreateTime(date);
                    deviceInfo.setUpdateTime(date);
                    deviceInfo.setSn(sn);
                    this.addDeviceInfo(deviceInfo);
                    deviceInfoCache.getCache().put(sn, deviceInfo);
                }
            }
        }
    }

    public void addDeviceData(DeviceData deviceData){
        if(null == deviceData.getCreateTime()){
            deviceData.setCreateTime(new Date());
        }
        deviceDataMapper.insert(deviceData);
    }

    public List<DeviceInfo> queryAllDeviceInfo(){
        return deviceInfoMapper.selectList(null);
    }

    @PostConstruct
    public void initDeviceInfoCache(){
        LocalCacheBuilder<Map<String,DeviceInfo>> builder = new LocalCacheBuilder<>();
        Map<String,DeviceInfo> cacheData = this.allDeviceInfo();
        deviceInfoCache = builder.build(30, cacheData, ()->  allDeviceInfo());
    }

    private Map<String,DeviceInfo> allDeviceInfo(){
        Map<String,DeviceInfo> deviceInfoMap = new ConcurrentHashMap<>();
        List<DeviceInfo> list = this.queryAllDeviceInfo();
        if(ObjectUtils.isNotEmpty(list)){
            for(DeviceInfo deviceInfo : list){
                deviceInfoMap.put(deviceInfo.getSn(),deviceInfo);
            }
        }
        return deviceInfoMap;
    }

}
